/**
 * TinyMCE version 7.7.1 (2025-03-05)
 */

(function() {
  "use strict";

  var global$2 = tinymce.util.Tools.resolve("tinymce.PluginManager");

  var global$1 = tinymce.util.Tools.resolve("tinymce.dom.RangeUtils");

  var global = tinymce.util.Tools.resolve("tinymce.util.Tools");

  const option = name => editor => editor.options.get(name);
  const register$2 = editor => {
    const registerOption = editor.options.register;
    registerOption("allow_html_in_named_anchor", {
      processor: "boolean",
      default: false
    });
  };
  const allowHtmlInNamedAnchor = option("allow_html_in_named_anchor");

  const namedAnchorSelector = "a:not([href])";
  const isEmptyString = str => !str;
  const getIdFromAnchor = elm => {
    const id = elm.getAttribute("id") || elm.getAttribute("name");
    return id || "";
  };
  const isAnchor = elm => elm.nodeName.toLowerCase() === "a";
  const isNamedAnchor = elm => isAnchor(elm) && !elm.getAttribute("href") && getIdFromAnchor(elm) !== "";
  const isEmptyNamedAnchor = elm => isNamedAnchor(elm) && !elm.firstChild;

  const removeEmptyNamedAnchorsInSelection = editor => {
    const dom = editor.dom;
    global$1(dom).walk(editor.selection.getRng(), nodes => {
      global.each(nodes, node => {
        if (isEmptyNamedAnchor(node)) {
          dom.remove(node, false);
        }
      });
    });
  };
  const isValidId = id => /^[A-Za-z][A-Za-z0-9\-:._]*$/.test(id);
  const getNamedAnchor = editor => editor.dom.getParent(editor.selection.getStart(), namedAnchorSelector);
  const getId = editor => {
    const anchor = getNamedAnchor(editor);
    if (anchor) {
      return getIdFromAnchor(anchor);
    } else {
      return "";
    }
  };
  const createAnchor = (editor, id) => {
    editor.undoManager.transact(() => {
      if (!allowHtmlInNamedAnchor(editor)) {
        editor.selection.collapse(true);
      }
      if (editor.selection.isCollapsed()) {
        editor.insertContent(editor.dom.createHTML("a", { id }));
      } else {
        removeEmptyNamedAnchorsInSelection(editor);
        editor.formatter.remove("namedAnchor", undefined, undefined, true);
        editor.formatter.apply("namedAnchor", { value: id });
        editor.addVisual();
      }
    });
  };
  const updateAnchor = (editor, id, anchorElement) => {
    anchorElement.removeAttribute("name");
    anchorElement.id = id;
    editor.addVisual();
    editor.undoManager.add();
  };
  const insert = (editor, id) => {
    const anchor = getNamedAnchor(editor);
    if (anchor) {
      updateAnchor(editor, id, anchor);
    } else {
      createAnchor(editor, id);
    }
    editor.focus();
  };

  const insertAnchor = (editor, newId) => {
    if (!isValidId(newId)) {
      editor.windowManager.alert("ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.");
      return false;
    } else {
      insert(editor, newId);
      return true;
    }
  };
  const open = editor => {
    const currentId = getId(editor);
    editor.windowManager.open({
      title: "Anchor",
      size: "normal",
      body: {
        type: "panel",
        items: [{
          name: "id",
          type: "input",
          label: "ID",
          placeholder: "example"
        }]
      },
      buttons: [
        {
          type: "cancel",
          name: "cancel",
          text: "Cancel"
        },
        {
          type: "submit",
          name: "save",
          text: "Save",
          primary: true
        }
      ],
      initialData: { id: currentId },
      onSubmit: api => {
        if (insertAnchor(editor, api.getData().id)) {
          api.close();
        }
      }
    });
  };

  const register$1 = editor => {
    editor.addCommand("mceAnchor", () => {
      open(editor);
    });
  };

  const isNamedAnchorNode = node => isEmptyString(node.attr("href")) && !isEmptyString(node.attr("id") || node.attr("name"));
  const isEmptyNamedAnchorNode = node => isNamedAnchorNode(node) && !node.firstChild;
  const setContentEditable = state => nodes => {
    for (let i = 0; i < nodes.length; i++) {
      const node = nodes[i];
      if (isEmptyNamedAnchorNode(node)) {
        node.attr("contenteditable", state);
      }
    }
  };
  const setup = editor => {
    editor.on("PreInit", () => {
      editor.parser.addNodeFilter("a", setContentEditable("false"));
      editor.serializer.addNodeFilter("a", setContentEditable(null));
    });
  };

  const registerFormats = editor => {
    editor.formatter.register("namedAnchor", {
      inline: "a",
      selector: namedAnchorSelector,
      remove: "all",
      split: true,
      deep: true,
      attributes: { id: "%value" },
      onmatch: (node, _fmt, _itemName) => {
        return isNamedAnchor(node);
      }
    });
  };

  const onSetupEditable = editor => api => {
    const nodeChanged = () => {
      api.setEnabled(editor.selection.isEditable());
    };
    editor.on("NodeChange", nodeChanged);
    nodeChanged();
    return () => {
      editor.off("NodeChange", nodeChanged);
    };
  };
  const register = editor => {
    const onAction = () => editor.execCommand("mceAnchor");
    editor.ui.registry.addToggleButton("anchor", {
      icon: "bookmark",
      tooltip: "Anchor",
      onAction,
      onSetup: buttonApi => {
        const unbindSelectorChanged = editor.selection.selectorChangedWithUnbind("a:not([href])", buttonApi.setActive).unbind;
        const unbindEditableChanged = onSetupEditable(editor)(buttonApi);
        return () => {
          unbindSelectorChanged();
          unbindEditableChanged();
        };
      }
    });
    editor.ui.registry.addMenuItem("anchor", {
      icon: "bookmark",
      text: "Anchor...",
      onAction,
      onSetup: onSetupEditable(editor)
    });
  };

  var Plugin = () => {
    global$2.add("anchor", editor => {
      register$2(editor);
      setup(editor);
      register$1(editor);
      register(editor);
      editor.on("PreInit", () => {
        registerFormats(editor);
      });
    });
  };

  Plugin();

})();
